package org.sqlproc.sample.tutorial.model;

import java.util.Date;
import java.util.HashSet;
import java.util.Set;

import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import javax.persistence.Version;

import org.hibernate.annotations.ForeignKey;
import org.hibernate.annotations.Type;
import org.hibernate.validator.constraints.NotEmpty;

/**
*
* Entity representing Library.
*/
@Entity
@Table(name = "LIBRARY")
//@EntityListeners({org.hibernate.validator.event.JPAValidateListener.class,
//    org.fornax.cartridges.sculptor.framework.domain.AuditListener.class
//})
public class Library {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Column(name = "ID")
    private Long id;
    @Column(name = "NAME", nullable = false, length = 100, unique = true)
    @NotEmpty
    private String name;
    @Column(name = "CREATEDDATE")
    @Type(type = "timestamp")
    private Date createdDate;
    @Column(name = "CREATEDBY", length = 50)
    private String createdBy;
    @Column(name = "LASTUPDATED")
    @Type(type = "timestamp")
    private Date lastUpdated;
    @Column(name = "LASTUPDATEDBY", length = 50)
    private String lastUpdatedBy;
    @Version
    @Column(name = "VERSION")
    private Long version;
    @OneToMany(cascade =  {
        CascadeType.ALL}
    , mappedBy = "library")
    @ForeignKey(name = "FK_LIBRARY_MEDIA_LIBRARY", inverseName = "FK_LIBRARY_MEDIA_MEDIA")
    @NotEmpty
    private Set<PhysicalMedia> media = new HashSet<PhysicalMedia>();

    public Library() {
    }

    public Library(String name) {
        super();
//        Validate.notNull(name);
        this.name = name;
    }

    public Long getId() {
        return id;
    }

    /**
     * The id is not intended to be changed or assigned manually, but
     * for test purpose it is allowed to assign the id.
     */
    protected void setId(Long id) {
        if ((this.id != null) && !this.id.equals(id)) {
            throw new IllegalArgumentException(
                "Not allowed to change the id property.");
        }
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public Date getCreatedDate() {
        return createdDate;
    }

    public void setCreatedDate(Date createdDate) {
        this.createdDate = createdDate;
    }

    public String getCreatedBy() {
        return createdBy;
    }

    public void setCreatedBy(String createdBy) {
        this.createdBy = createdBy;
    }

    public Date getLastUpdated() {
        return lastUpdated;
    }

    public void setLastUpdated(Date lastUpdated) {
        this.lastUpdated = lastUpdated;
    }

    public String getLastUpdatedBy() {
        return lastUpdatedBy;
    }

    public void setLastUpdatedBy(String lastUpdatedBy) {
        this.lastUpdatedBy = lastUpdatedBy;
    }

    public Long getVersion() {
        return version;
    }

    public void setVersion(Long version) {
        this.version = version;
    }

    public Set<PhysicalMedia> getMedia() {
        return media;
    }

    /**
     * Adds an object to the bidirectional many-to-one
     * association in both ends.
     * It is added the collection {@link #getMedia}
     * at this side and the association
     * {@link org.fornax.cartridges.sculptor.examples.library.media.domain.PhysicalMedia#setLibrary}
     * at the opposite side is set.
     */
    public void addMedia(PhysicalMedia mediaElement) {
        this.media.add(mediaElement);
        mediaElement.setLibrary((Library) this);
    }

    /**
     * Removes an object from the bidirectional many-to-one
     * association in both ends.
     * It is removed from the collection {@link #getMedia}
     * at this side and the association
     * {@link org.fornax.cartridges.sculptor.examples.library.media.domain.PhysicalMedia#setLibrary}
     * at the opposite side is cleared (nulled).
     */
    public void removeMedia(PhysicalMedia mediaElement) {
        this.media.remove(mediaElement);
        mediaElement.setLibrary(null);
    }

    /**
     * Removes all object from the bidirectional
     * many-to-one association in both ends.
     * All elements are removed from the collection {@link #getMedia}
     * at this side and the association
     * {@link org.fornax.cartridges.sculptor.examples.library.media.domain.PhysicalMedia#setLibrary}
     * at the opposite side is cleared (nulled).
     */
    public void removeAllMedia() {
        for (PhysicalMedia d : this.media) {
            d.setLibrary(null);
        }
        this.media.clear();

    }

    /**
     * This method is used by equals and hashCode.
     * @return {@link #getName}
     */
    public Object getKey() {
        return getName();
    }
}
